﻿#!/usr/bin/python
# coding:utf-8

# import pdb
import sys
import serial
import serial.tools.list_ports
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from time import *

QTextCodec.setCodecForTr(QTextCodec.codecForName("utf8"))


def list_all_com():
    ports = list(serial.tools.list_ports.comports())
    COM = []
    for item in ports:
        COM.append(item[0])
    return COM


class MainWindow(QMainWindow):
    recvSignal = pyqtSignal()
    stringText = '1'

    def __init__(self):
        super(MainWindow, self).__init__()
        self.resize(250 * 5, 150 * 5)
        self.setWindowTitle(self.tr('串口助手'))
        self.setWindowIcon(QIcon('icons/chrome_bw.png'))
        self.ser = serial.Serial()
        self.textString = None
        # 子线程变量
        self.thread = ReceiveThread(self.ser,self.test)

        # 自定义的信号
        self.receiveGot = pyqtSignal([int], [str])

        # 成员变量
        self.COM = self.tr('COM1')
        self.PARITY = self.tr('None')
        self.STOPBIT = self.tr('1')
        self.BAUD = self.tr('115200')
        self.comStatus = self.tr('已关闭')


        # 动作控件
        open = QAction(QIcon('icons/serial_port.png'), self.tr('打开串口(&O)'), self)
        open.setShortcut('Ctrl+O')
        open.setStatusTip(self.tr('配置并打开串口'))
        open.setToolTip(self.tr('<b>配置并打开串口</b>'))
        open.connect(open, SIGNAL('triggered()'), self.open_port)

        save = QAction(QIcon('icons/save.png'), self.tr('保存(&S)'), self)
        save.setShortcut('Ctrl+S')

        exit = QAction(QIcon('icons/exit.png'), self.tr('退出(&Q)'), self)
        exit.setShortcut('Ctrl+Q')
        exit.setStatusTip(self.tr('退出程序'))
        exit.setToolTip(self.tr('退出程序'))
        exit.connect(exit, SIGNAL('triggered()'), qApp, SLOT('quit()'))

        copy = QAction(QIcon('icons/copy.png'), self.tr('复制(&C)'), self)
        copy.setStatusTip(self.tr('复制选择的文本'))

        # 菜单栏，工具栏添加
        self.statusBar()
        menubar = self.menuBar()

        file = menubar.addMenu(self.tr('文件(&F)'))
        file.addAction(open)
        file.addAction(save)
        file.addAction(exit)

        edit = menubar.addMenu(self.tr('编辑(&E)'))
        edit.addAction(copy)

        self.toolbar = self.addToolBar(self.tr('退出'))
        self.toolbar.addAction(save)
        self.toolbar.addAction(open)
        self.toolbar.addAction(copy)
        self.toolbar.addAction(exit)

        self.textBrowser = QTextBrowser()  # 接收显示控件
        self.receiveButton = QPushButton(self.tr('开始接收'))
        self.connect(self.receiveButton, SIGNAL('clicked()'), self.recThread)
        self.connect(self.receiveButton, SIGNAL('clicked()'), self.thread.start)

        self.lineEditor = QLineEdit()  # 发送输入控件
        self.sendButton = QPushButton(self.tr('发送'))  # 发送按钮
        self.sendButton.connect(self.sendButton, SIGNAL('clicked()'), self.send)

        # 接收选项布局
        hbox_receive = QHBoxLayout()

        vbox_receive_sub = QVBoxLayout()
        vbox_receive_sub.addStretch()
        vbox_receive_sub.addWidget(self.receiveButton)

        hbox_receive.addWidget(self.textBrowser)
        hbox_receive.addLayout(vbox_receive_sub)


        # 发送行布局
        hbox_send = QHBoxLayout()
        hbox_send.addWidget(self.lineEditor)
        hbox_send.addWidget(self.sendButton)

        # 发送选项
        hbox_send_set = QHBoxLayout()
        sendNewLine = QCheckBox(self.tr('发送换行'))
        self.comSwitch = QPushButton(self.tr("打开串口"))
        self.comSwitch.connect(self.comSwitch, SIGNAL('clicked()'), self.on_off)
        hbox_send_set.addStretch()
        hbox_send_set.addWidget(self.comSwitch)
        hbox_send_set.addWidget(sendNewLine)

        # 设置垂直布局管理器
        vbox = QVBoxLayout()
        vbox.addLayout(hbox_receive)
        vbox.addLayout(hbox_send)
        vbox.addLayout(hbox_send_set)

        # 中心控件设置
        centralWidget = QWidget()

        centralWidget.setLayout(vbox)

        self.setCentralWidget(centralWidget)

    def open_port(self):
        dialog = QDialog()
        dialog.setWindowTitle(self.tr('串口设置'))
        dialog.setWindowIcon(QIcon('icons/serial_port.png'))
        COMS = list_all_com()

        baud = ['115200', '110', '300', '600', '1200', '2400', '4800', '9600', '14400', '19200', '38400', '5600',
                '57600', '128000', '256000']

        stopbit = [self.tr('1'), self.tr('2')]

        parity = [self.tr('None'), self.tr('ODD'), self.tr('EVEN')]

        comList = QComboBox()
        comList.addItems(COMS)

        baudList = QComboBox()
        baudList.addItems(baud)

        parityList = QComboBox()
        parityList.addItems(parity)

        stopbitList = QComboBox()
        stopbitList.addItems(stopbit)

        portLabel = QLabel(self.tr('端口'))

        baudLabel = QLabel(self.tr('波特率'))

        parityLabel = QLabel(self.tr("奇偶校验"))

        stopbitLabel = QLabel(self.tr("停止位"))

        hbox1 = QHBoxLayout()
        hbox1.addWidget(portLabel)
        hbox1.addWidget(comList)
        hbox1.addWidget(baudLabel)
        hbox1.addWidget(baudList)
        hbox1.addWidget(parityLabel)
        hbox1.addWidget(parityList)
        hbox1.addWidget(stopbitLabel)
        hbox1.addWidget(stopbitList)

        okButton = QPushButton(self.tr('确定'))
        okButton.connect(okButton, SIGNAL('clicked()'), dialog, SLOT('accept()'))
        cancleButton = QPushButton(self.tr('取消'))
        cancleButton.connect(cancleButton, SIGNAL('clicked()'), dialog, SLOT('reject()'))

        hbox2 = QHBoxLayout()
        hbox2.addStretch()
        hbox2.addWidget(okButton)
        hbox2.addWidget(cancleButton)

        vbox = QVBoxLayout()
        vbox.addLayout(hbox1)
        vbox.addLayout(hbox2)

        dialog.setLayout(vbox)

        if dialog.exec_():
            self.COM = comList.currentText()
            self.BAUD = baudList.currentText()
            self.PARITY = parityList.currentText()
            self.STOPBIT = stopbitList.currentText()
            if self.ser.isOpen():
                try:
                    self.ser.close()
                except:
                    errorMessage = QMessageBox.question(dialog, self.tr('异常'), self.tr('串口关闭异常'), QMessageBox.Yes)
                    if errorMessage == QMessageBox.Yes:
                        self.setStatusTip(self.COM + self.tr("关闭异常"))

            try:
                self.ser = serial.Serial(unicode(QString(self.COM).toUtf8(), 'utf-8', 'ignort'),
                                         int(unicode(QString(self.BAUD).toUtf8(), 'utf-8', 'ignort')), timeout=1)
                if self.ser.isOpen:
                    self.setWindowTitle(self.COM + ':' + self.BAUD + ':' + self.PARITY + ':' + self.STOPBIT)
                    # self.ser = serial.Serial(unicode(QString(self.COM).toUtf8(),'utf-8','ignort'),int(unicode(QString(self.BAUD).toUtf8(),'utf-8','ignort')),timeout = 1)
                    self.comStatus = self.tr("已打开")
                    self.comSwitch.setText(self.tr('关闭串口'))
                    self.setStatusTip(
                        self.COM + ':' + self.BAUD + ':' + self.PARITY + ':' + self.STOPBIT + ':' + self.comStatus)

                else:
                    self.setStatusTip(self.COM + self.tr("打开失败"))
            except:
                errorMessage = QMessageBox.question(dialog, self.tr('异常'), self.tr('串口打开异常'), QMessageBox.Yes)
                if errorMessage == QMessageBox.Yes:
                    self.setStatusTip(self.COM + self.tr("打开异常"))
                self.setStatusTip(self.COM + self.tr("打开异常"))
                self.comStatus = self.tr('异常')


        else:
            self.setStatusTip(self.tr('设置未改变'))

    def status_get(self):
        self.setStatusTip(self.COM + ':' + self.BAUD + ':' + self.PARITY + ':' + self.STOPBIT + ':' + self.comStatus)

    def on_off(self):

        if self.comStatus == self.tr("已打开"):
            try:
                self.ser.close()
                if False == self.ser.isOpen():
                    self.comStatus = self.tr('已关闭')
                    self.comSwitch.setText(self.tr('打开串口'))
                    self.comSwitch.setToolTip(self.tr('当前串口已关闭'))
                    self.setStatusTip(self.tr('已关闭'))
            except:
                errorMessage == QMessageBox.question(self, self.tr('异常'), self.tr('串口关闭异常'), QMessageBox.Yes)
                self.setStatusTip(self.tr('串口关闭异常'))
        elif self.comStatus == self.tr('已关闭'):
            try:
                self.ser = serial.Serial(unicode(QString(self.COM).toUtf8(), 'utf-8', 'ignort'),
                                         int(unicode(QString(self.BAUD).toUtf8(), 'utf-8', 'ignort')), timeout=1)
                if True == self.ser.isOpen():
                    self.comStatus = self.tr('已打开')
                    self.comSwitch.setText(self.tr('关闭串口'))
                    self.comSwitch.setToolTip(self.tr('当前串口已打开'))
                    self.setStatusTip(self.tr('已打开'))
            except:
                errorMessage = QMessageBox.question(self, self.tr('异常'), self.tr('串口打开异常'), QMessageBox.Yes)
                if self.ser.isOpen:
                    self.setWindowTitle(self.COM + ':' + self.BAUD + ':' + self.PARITY + ':' + self.STOPBIT)
                    self.comStatus = self.tr("已打开")
                    self.setStatusTip(
                        self.COM + ':' + self.BAUD + ':' + self.PARITY + ':' + self.STOPBIT + ':' + self.comStatus)
                else:
                    self.setStatusTip(self.COM + self.tr("打开失败"))
        elif self.comStatus == self.tr('异常'):
            message = QMessageBox.question(self, self.tr('异常'), self.tr('串口状态异常'), QMessageBox.Yes)
            self.setStatusTip(self.tr('串口处于异常状态'))
        else:
            message = QMessageBox.question(self, self.tr('异常'), self.tr('串口状态未知'), QMessageBox.Yes)

    def send(self):
        print 'send'
        if self.ser.isOpen() == True:
            strings = unicode(QString(self.lineEditor.text()).toUtf8(), 'utf-8', 'ignort')
            self.ser.write(strings.encode())
            print (strings.encode())
            self.lineEditor.clear()
        else:
            message = QMessageBox.question(self, self.tr('异常'), self.tr('请确定串口已经正常打开'), QMessageBox.Yes)
            if message == QMessageBox.Yes:
                self.setStatusTip(self.tr('请打开串口！'))

    def receive(self):
        while 1:
            print 'receive'
            if self.ser.isOpen() == True:
                count = self.ser.inWaiting()
                if count > 0:
                    self.textString = self.tr(ser.read(count))
                    self.emit(SIGNAL('textgot'), self.textString)

    def textUpdate(self, string):
        print 'textupdate'
        self.textBrowser.append(string)

    def recThread(self):
        self.recvSignal.emit()
        # thread = ReceiveThread()
        # thread.recvSignal.connect(self.textUpdate)
        # thread.start()

    def recvSignalText(self, string):
        print string

    def test(self, string):

        self.stringText += string
        print self.stringText


class ReceiveThread(QThread):
    recvSignal = pyqtSignal(str)

    def __init__(self, ser, func):
        super(ReceiveThread, self).__init__()
        self.ser  = ser
        self.func = func

    def run(self):
        while True:
            print 'child'
            self.recvSignal.emit('Hello')
            # pdb.set_trace()
            if self.ser.isOpen == True:
                print str(self.ser.name) + 'Opened'
            self.func('12')
            sleep(0.5)

    def stop(self):
        self.exit()


app = QApplication(sys.argv)
main = MainWindow()

# t1 = ReceiveThread(main.recvSignalText)
# main.recvSignal.connect(t1.start)
# t1.recvSignal.connect(main.textUpdate)

main.show()
sys.exit(app.exec_())
